亲爱的小朋友们,当你们打开这本书时,相信你们已经开始了C++编程的学习之旅,甚至可能正在进入算法学习的精彩阶段。你们中的许多人,或许正在为编程等级考试或信息学竞赛做准备。在学习过程中,你们可能发现了一个有趣的现象,很多编程题目都包含着丰富的数学知识,有些内容甚至超出了你们当前数学课程的进度,比如平方根、立方根、函数等概念。
你们可能会非常困惑。信息学竞赛为什么会用到这么多数学知识?参加信息学竞赛到底要掌握哪些数学知识?是不是奥数学好了,学习算法时就没有障碍了?现在我就来逐一解答这些困惑。
计算机(computer)最初就是为“计算”而设计的。世界上第一台电子计算机ENIAC诞生于1946年,当时研制计算机的目的是解决复杂的弹道计算问题。尽管现在的计算机功能非常强大,除了可以用来做科学计算,还可以用来办公、学习、娱乐,也可以运行当前各种炫酷的人工智能应用程序,但是,无论多复杂的功能,计算机都是将它们转换成各种计算。要理解和熟练应用这些计算,就需要学好数学。此外,信息学竞赛的核心是算法设计,而算法是建立在数学基础之上的。所以,信息学竞赛需要掌握很多数学知识。
信息学竞赛涉及的数学知识包括在小学阶段学的所有初等数学基础和初等几何知识,以及在小学阶段课本上基本学不到的数列问题及递推和递归、进制及进制转换、数论基础、集合论、组合数学、图论基础、树及二叉树、概率论基础、逻辑学基础、编码及译码、博弈论基础、算法及算法复杂度等。
这么多数学知识,中学生甚至小学生能掌握吗?我觉得是可以的,因为同学们只需要理解这些数学知识背后的思想和原理,不需要手工求解这些数学问题。我们的目标是根据数学原理,设计算法,编写程序,让计算机来帮我们解决这些问题。而且这些数学知识不是在学习C++和算法前就必须全部掌握的,也就是说不是预备知识,而是贯穿于C++和算法学习的整个阶段的。
以平方根为例,小学阶段的数学没法讲平方根运算,因为手工求、等是求不出来的,但同学们只要理解了平方根的含义,知道平方根是平方的相反运算,在C++程序中知道如何调用sqrt()函数求平方根就可以了。又如,组合数学中有很多复杂的排列组合问题,对小学生来说太难了,但是在信息学竞赛里主要应用的是组合数学里的一些原理,比如,加法原理、乘法原理、鸽巢原理等。
既然信息学竞赛需要掌握很多数学知识,那么同学们直接学奥数不就可以了吗?注意,C++编程与信息学竞赛中的数学不等于奥数。奥数更多的是训练学生的计算技巧和动手解决应用问题的能力,但是这些计算技巧在C++编程与信息学竞赛中完全没有用武之地。因为编程的目的之一就是把所有计算交给程序来实现,而且奥数里津津乐道的各种应用题,在信息学竞赛的试题里几乎不会出现,此外,奥数几乎不涉及算法。所以,同学们需要专门学习信息学竞赛的数学基础知识。
本书就是一本专门讲C++编程与信息学竞赛数学基础的书,既是数学书也是编程书,侧重数学原理在编程中的应用。为了降低门槛,本书把算法难度控制在基础级,只用到了枚举、模拟、递推、递归等简单算法,此外也用到C++语言标准模板库中的容器,包括位组(bitset)、集合(set)、数对(pair)等。
最后,祝小朋友们能感受到数学之美,体会到学习数学和编程的快乐,在快乐中学习。